package net.sf.google.talk.eclipse.proxy;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.SocketFactory;

/**
 * Socket Factory to use with XMPPConnection for connection through a SOCKS Proxy server.
 * @author raul.neto
 *
 */
public class ProxySocketFactory extends SocketFactory {

    private String proxyHost;
    private int    proxyPort;

    public ProxySocketFactory(){super();}
    
    /**
     * Convenience Constructor providing proxy host and Port.
     * @param theProxyHost Provide your proxy host. If null or blank throws <code>IllegalArgumentException</code>.
     * @param theProxyPort Provide your proxy host. If negative throws <code>IllegalArgumentException</code>.
     */
    public ProxySocketFactory( String theProxyHost, int theProxyPort ) {
        if(theProxyHost == null || "".equals(theProxyHost.trim())){
            throw new IllegalArgumentException("Invalid proxy host name (or ip):"+theProxyHost);
        }
        if(theProxyPort <0){
            throw new IllegalArgumentException("Invalid proxy port:"+theProxyPort);
        }
        this.proxyHost = theProxyHost;
        this.proxyPort = theProxyPort;
    }

    private Proxy getProxy() {
        InetSocketAddress ps = new InetSocketAddress( proxyHost, proxyPort );
        Proxy p = new Proxy( Proxy.Type.SOCKS, ps );
        return p;
    }

    @Override
    public Socket createSocket( String host, int port ) throws IOException, UnknownHostException {
        Socket newSocket = new Socket( getProxy() );
        newSocket.connect( new InetSocketAddress( host, port ) );
        return newSocket;
    }

    @Override
    public Socket createSocket( InetAddress host, int port ) throws IOException {
        Socket newSocket = new Socket( getProxy() );
        newSocket.connect( new InetSocketAddress( host, port ) );
        return newSocket;
    }

    @Override
    public Socket createSocket( String host, int port, InetAddress localHost, int localPort ) throws IOException, UnknownHostException {
        Socket newSocket = new Socket( getProxy() );
        newSocket.bind( new InetSocketAddress( localHost, localPort ) );
        newSocket.connect( new InetSocketAddress( host, port ) );
        return newSocket;
    }

    @Override
    public Socket createSocket( InetAddress address, int port, InetAddress localAddress, int localPort ) throws IOException {
        Socket newSocket = new Socket( getProxy() );
        newSocket.bind( new InetSocketAddress( localAddress, localPort ) );
        newSocket.connect( new InetSocketAddress( address, port ) );
        return newSocket;
    }

    
    public String getProxyHost() {
        return proxyHost;
    }

    
    public void setProxyHost( String proxyHost ) {
        this.proxyHost = proxyHost;
    }

    
    public int getProxyPort() {
        return proxyPort;
    }

    
    public void setProxyPort( int proxyPort ) {
        this.proxyPort = proxyPort;
    }
}
